﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using QuartzTypeLib;

// 動画
// http://code-life.net/?p=1521

// CSV
// http://whoopsidaisies.hatenablog.com/entry/2013/11/22/130256

namespace TimingWithVideo
{
    public partial class Form1 : Form
    {
        // video用
        OpenFileDialog ofdv;
        FilgraphManager fgm;
        IBasicVideo bv;
        IVideoWindow vw;
        IMediaEventEx mevent;

        // Lyrics用
        OpenFileDialog ofdl;
        List<long> timings = new List<long>();
        List<Tim2> tims = new List<Tim2>();
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            btnVideoFile.Enabled = true;
            btnLyrics.Enabled = false;
            btnPlay.Enabled = false;
            timer1.Enabled = false;
            sw.Reset();
        }

        private void btnVideoFile_Click(object sender, EventArgs e)
        {
            ofdv = new OpenFileDialog();
            ofdv.FileName = "NewTiming.avi";
            ofdv.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            ofdv.Filter = "メディアファイル(*.avi;*.mpg;*.wmv)|*.avi;*.mpg;*.wmv|すべてのファイル|*.*";
            ofdv.ShowHelp = true;
            if (ofdv.ShowDialog() == DialogResult.OK)
            {
                fgm = new FilgraphManager();
                fgm.RenderFile(ofdv.FileName);
                bv = (IBasicVideo)fgm;
                vw = (IVideoWindow)fgm;
                mevent = (IMediaEventEx)fgm;

                int vx, vy;
                bv.GetVideoSize(out vx, out vy);

                vw.Owner = (int)this.Handle;
                vw.WindowStyle = 0x40000000 | 0x4000000;

                vw.SetWindowPosition(0, 0, vx, vy);

                mevent.SetNotifyWindow((int)this.Handle, 0x8000, 0);

                btnLyrics.Enabled = true;
                btnVideoFile.Enabled = false;
                lblVideoSelect.Text = ofdv.FileName;
                btnLyrics.Focus();
            }
        }

        private void btnLyrics_Click(object sender, EventArgs e)
        {
            ofdl = new OpenFileDialog();
            ofdl.FileName = "NewTiming.txt";
            ofdl.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\";
            ofdl.RestoreDirectory = true;
            ofdl.ShowHelp = true;
            if (ofdl.ShowDialog() == DialogResult.OK)
            {
                try
                {   // ファイルの解読
                    System.IO.StreamReader sr = new System.IO.StreamReader(
                        ofdl.FileName, Encoding.GetEncoding("Shift_JIS"));
                    while (!sr.EndOfStream)
                    {
                        string line = sr.ReadLine();
                        string[] values = line.Split(',');
                        tims.Add( new Tim2(long.Parse(values[0]), values[1] ) );
                    }
                    sr.Close();

                    btnPlay.Enabled = true;
                    timer1.Interval = 10;
                    timer1.Enabled = true;
                    lblLyricsSelect.Text = ofdl.FileName;
                    btnPlay.Focus();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to read" + ofdl.FileName + "\t" + ex.Message);
                }
            }
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            btnVideoFile.Enabled = false;
            btnLyrics.Enabled = false;
            btnPlay.Enabled = false;
            sw.Reset();
            fgm.Run();
            System.Threading.Thread.Sleep(200);
            sw.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            pbStage.Refresh();
        }

        private void pbStage_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawLine(Pens.Black, 50, 50, 450, 50);
            e.Graphics.DrawLine(Pens.Black, 80, 20, 80, 80);

            if (sw.IsRunning)
            {
                long now = sw.ElapsedMilliseconds;
                foreach( Tim2 tim in tims)
                {
                    tim.paint(e.Graphics, now);
                }
                lblTimer.Text = ((double)sw.ElapsedMilliseconds / 1000).ToString();
            }
        }
    }

/*    class Tim
    {
        long tim;
        long speed = 400;    // [pixel/sec]
        int x0 = 50;
        int y0 = 50;
        int rad = 10;

        public void paint(Graphics g, long t)
        {
            int posx = x0 + (int)(speed * (tim - t) / 1000);
            g.FillEllipse(Brushes.Red, posx - rad, y0 - rad, 2 * rad, 2 * rad);
        }

        public Tim(long tim)
        {
            this.tim = tim;
        }
    }
    */

    // 入力時刻,入力文字
    class Tim2
    {
        long timing;
        string letter;
        long speed = 400;
        long echoLen = 50;
        long dt = 5;
        int x0 = 50;
        int y0 = 50;
        int rad = 15;
        int fontsize = 20;
        Pen rpen = new Pen(Color.Red, 3);

        public void paint(Graphics g, long t)
        {
            int posx = x0 + (int)(speed * (timing - t) / 1000);
            g.DrawEllipse(rpen, posx - rad, y0 - rad, 2 * rad, 2 * rad);
            g.DrawString(letter, new Font("IPA Gothic", fontsize), Brushes.Black, posx - rad, y0 - rad);
            if (((t - dt) < timing) && (timing < (t + dt + echoLen)))
            {
                g.FillEllipse(Brushes.Red, 55, 25, 50, 50);
            }
        }

        public Tim2(long timing, string letter, long dt=5)
        {
            this.timing = timing;
            this.letter = letter;
            this.dt = dt;
        }
    }
}
